home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / DIAG / INTR26B.ARJ / INT2GUID.C < prev    next >
Text File  |  1991-05-12  |  14KB  |  539 lines

  1. /* INT2GUID.C
  2.  *
  3.  * from:
  4.  * INT2QH.C
  5.  *
  6.  * Author:   Kai Uwe Rommel
  7.  * Date:     Sun 07-Oct-1990
  8.  * Update:   Sat 20-Oct-1990
  9.  * Update:   Sun 11-Nov-1990  Ralf Brown
  10.  *
  11.  * Compiler: MS C 5.00 and newer / compact model, or TC 2.0 / compact model
  12.  * System:   PC/MS-DOS 3.20 and newer, OS/2 1.0 and newer
  13.  *
  14.  *
  15.  * INT2GUID.C is a TurboPower GUIDE/MAKEHELP version of INT2QH.C
  16.  *
  17.  * Transscriptor:    Bent Lynggaard
  18.  * Date:        Sun 24-Mar-1991
  19.  * Update:        Tue 02-Apr-1991    - test '!', ';' in line pos 1.
  20.  *                    - test disk full
  21.  *            Sun 14-Apr-1991    - smaller index pages
  22.  *                    - main index always leads to start of
  23.  *                      an INT #
  24.  *            Sun 12-May-1991    - configuration file.
  25.  *
  26.  * This program creates output to the standard output device. The output
  27.  * should be redirected to a file INTERRUP.TXT. The created file should
  28.  * be compiled by the TurboPower MAKEHELP program to a INTERRUP.HLP file,
  29.  * which can be interpreted by the TurboPower GUIDE TSR program:
  30.  *    INT2GUID > [ramdisk:]INTERRUP.TXT
  31.  *    MAKEHELP [ramdisk:INTERRUPT] INTERRUP[.HLP] /Q
  32.  *    GUIDE INTERRUP    (or enter GUIDE with a hot key, press F3,
  33.  *            enter INTERRUP)
  34.  *
  35.  * The following is considered in creating the topic (and popup window)
  36.  * headers:
  37.  * The first word in the header is the interrupt number, so that GUIDE's
  38.  * search mechanism can find the entry if the hot key is pressed when
  39.  * the cursor is at an interrupt number.
  40.  * MAKEHELP restricts the (length of longest header + 1) times the number
  41.  * of topics to 64 kB. INTER191 had about 2200 topics, so the length of
  42.  * the headers should be limited to 25 characters. However, rather than
  43.  * truncating the INTERRUP.LST header lines to some nonsence, this
  44.  * program uses only the interrupt number as topic headings, plus the
  45.  * AH or AX values where applicable.
  46.  * The main index references some subindeces. The subindeces use the
  47.  * MAKEHELP cross reference facility. MAKEHELP limits the number of cross
  48.  * references to 50 per topic, however, this program limits each subindex
  49.  * to 18 entries, so each "topic" can be shown on one single screen with
  50.  * height 20 lines. For each interrupt number, the entries are temporarily
  51.  * stored, and written to the current subindex page only if all entries
  52.  * for the interrupt number fit on the page.
  53.  *
  54.  * MAKEHELP's text wrapping mechanism is disabled, and as the active
  55.  * window is limited to 76 characters, some lines are missing one or two
  56.  * characters.
  57.  * The amount of text that can be displayed per topic is limited by
  58.  * GUIDE's setting of pages/topic (default = 20) and the screen height
  59.  * defined when GUIDE was initialized.
  60.  *
  61.  */
  62.  
  63. #define LABEL    "int2guid.c"
  64. #define VERSION  "1.03"
  65.  
  66. #include <stdio.h>
  67. #include <stdlib.h>
  68. #include <string.h>
  69. #include <ctype.h>
  70.  
  71. #define divider_line(s) (strncmp(s,"--------",8)==0)
  72. #define maxIndeces 18
  73.   /* max 50, 18 gives one page with height 20 (18 active lines) */
  74. #define mainIndex 200
  75.   /* 1-99 reserved for program, 100-199 reserved for user */
  76. #define false 0
  77. #define true 1
  78.  
  79. FILE *input, *output, *topics, *subtopics, *config;
  80.  
  81. char line1[128];
  82. char line2[128];
  83. char tempBuffer[50 * 128];
  84. char *tempPtr;
  85. char category[4] = "--";
  86. char infilename[14] = "interrup.lst";
  87. #define infileExt 9
  88. int splitInfile = 0;
  89.  
  90. char configfile[14] = "int2guid.cfg";
  91. char configmarker[18] = "INT2GUIDE CONFIG";
  92.  
  93. char missingFile[] = "Missing include file.";
  94.  
  95. int sub = 0, indexed = 1;
  96. unsigned currentID = 1, activeID = 1, indeces = 0, indexNo = 0, buffered = 0,
  97.   subindeces, activeSub;
  98.  
  99. void exitfunc(void)
  100. {
  101.   fcloseall();
  102.   unlink("topic.tmp");
  103.   unlink("subtopic.tmp");
  104. }
  105.  
  106. void errorexit(char *msg)
  107. /* writes msg to stderr and exits with error code 1 */
  108. {
  109.   fputs(msg, stderr);
  110.   exit(1);
  111. } /* errorexit */
  112.  
  113. void diskFull(int temporary)
  114. /* reports disk full and exits */
  115. {
  116.   char msg[80];
  117.   sprintf(msg,"\n\nDisk full, %s file\n", temporary ? "temporary" : "output");
  118.   errorexit(msg);
  119. } /* diskFull */
  120.  
  121.  
  122. int _fputs(char *line, FILE *stream)
  123. /* filters TABs to spaces, and inserts a leading space in lines starting
  124.    with the MAKEHELP command and comment characters '!' and ';'. "_fputs"
  125.    should be used when copying from unknown sources. Use "fputs" when
  126.    copying files with information specifically for this program.
  127. */
  128. {
  129.   char buffer[128];
  130.   int cnt = 0;
  131.  
  132.   if ( (*line=='!') || (*line==';') ) /* MAKEHELP command/comment? */
  133.     buffer[cnt++] = ' '; /* start with a space */
  134.  
  135.   while ( *line )
  136.   {
  137.     switch ( *line )
  138.     {
  139.       case '\t': do buffer[cnt++] = ' '; while ( cnt & 7 ); break;
  140.             /* MAKEHELP does not interpret tabs */
  141.       default  : buffer[cnt++] = *line;
  142.     }
  143.     line++;
  144.   }
  145.  
  146.   buffer[cnt] = 0;
  147.  
  148.   if ( (cnt = fputs(buffer, stream)) == EOF )
  149.     diskFull(stream != output);
  150.  
  151.   return cnt;
  152. }
  153.  
  154. char *_fgets(char *s, int n, FILE *stream)
  155. {
  156.   char *ptr;
  157.   ptr = fgets(s, n, stream);
  158.   if ( (ptr==NULL) && (stream==input) && splitInfile )
  159.   {
  160.     fclose(input);
  161.     infilename[infileExt]++;
  162.     input = fopen(infilename, "r");
  163.     if ( input != NULL )
  164.     {
  165.       fprintf(stderr, "%s\n", infilename);
  166.       ptr = fgets(s, n, input);
  167.     }
  168.   }
  169.   return ptr;
  170. } /* _fgets */
  171.  
  172. void Initialize(void)
  173. {
  174.   input     = fopen(infilename, "r");
  175.   if ( input == NULL )
  176.   {
  177.     infilename[infileExt] = 'a';
  178.     infilename[infileExt+1] = 0;
  179.     input = fopen(infilename, "r");
  180.     if ( input == NULL )
  181.     {
  182.       fputs("Cannot open input file (INTERRUP.LST or INTERRUP.A)\n", stderr);
  183.       exit(1);
  184.     }
  185.     splitInfile = 1;
  186.   }
  187.   fprintf(stderr, "%s\n", infilename);
  188.   output    = stdout;
  189.   topics    = fopen("topic.tmp", "w");
  190.   subtopics = fopen("subtopic.tmp", "w");
  191.  
  192.   tempPtr = tempBuffer;
  193.  
  194.   fprintf(output,
  195.     ";INTERRUPT help text for MAKEHELP/GUIDE.\n;\n!WIDTH 80\n;\n");
  196.   fprintf(topics, "!TOPIC 1 Interrupt List\n!INDEX %u\n", mainIndex);
  197. }
  198.  
  199.  
  200. void testTopic(void) /* limit xrefs/topic to maxIndeces */
  201. {
  202.   if ( indeces+buffered >= maxIndeces ) /* leave one entry for forw. ref */
  203.   {
  204.     currentID++;
  205.     fprintf(topics, "\004%u\005INT %s\005 (index continued)\n"
  206.       "!TOPIC %u INT %s (cont)\n!INDEX %u\n"
  207.       "(continued \004%u\005from\005)\n",
  208.       currentID, category, currentID, category, ++indexNo, activeID);
  209.     indeces = 1; /* the backwards ref */
  210.     activeID = currentID;
  211.   }
  212. } /* testTopic */
  213.  
  214. void copyBuffer(void)
  215. {
  216.   if ( buffered == 0 )
  217.     return;
  218.  
  219.   testTopic();
  220.   if ( fputs(tempBuffer, topics) == EOF )
  221.       diskFull(true);
  222.   indeces += buffered;
  223.   buffered = 0;
  224.   tempPtr = tempBuffer;
  225. } /* copyBuffer */
  226.  
  227. void Cleanup(void)
  228. {
  229.   copyBuffer();
  230.   fclose(topics);
  231.   fclose(subtopics);
  232.   fputs("Cleaning up\n", stderr);
  233.  
  234.   topics = fopen("topic.tmp", "r");
  235.   subtopics = fopen("subtopic.tmp", "r");
  236.  
  237.   while ( fgets(line1, sizeof(line1), topics) )
  238.     if ( fputs(line1, output) == EOF )
  239.       diskFull(false);
  240.  
  241.   while ( fgets(line1, sizeof(line1), subtopics) )
  242.     if ( fputs(line1, output) == EOF )
  243.       diskFull(false);
  244. }
  245.  
  246.  
  247. int CopyFile(char *name, int commands)
  248. /* copies a file to the database, returns 0 for success or 1 for error */
  249. {
  250.   FILE *temp = fopen(name, "r");
  251.   fprintf(stderr, "%s\n", name);
  252.   if ( temp == NULL )
  253.   {
  254.     fprintf(stderr, "WARNING: Could not open %s\n", name);
  255.     fputs("Information was not available\n", output);
  256.     return 1;
  257.   }
  258.   else
  259.   {
  260.     while ( fgets(line2, sizeof(line2), temp) )
  261.       commands ? fputs(line2, output) : _fputs(line2, output);
  262.     fputs("!NOWRAP\n", output); /* in case it was left in !WRAP state */
  263.     fclose(temp);
  264.     return 0;
  265.   }
  266. } /* CopyFile */
  267.  
  268. void testSubtopic(char *marker)
  269. {
  270.   if ( ++subindeces >= maxIndeces )
  271.   {
  272.     sprintf(tempPtr, "\004%u\005%s\005  (list cont.)\n",
  273.       ++currentID, marker);
  274.     tempPtr += strlen(tempPtr);
  275.     buffered++;
  276.     fprintf(subtopics,
  277.       "\004%u\005%s\005  (list cont.)\n!TOPIC %u %s (list cont)\n!NOINDEX\n"
  278.       "(continued \004%u\005from\005)\n",
  279.       currentID, marker, currentID, category, activeSub);
  280.       activeSub = currentID;
  281.     subindeces = 2;
  282.   }
  283. } /* testSubtopic */
  284.  
  285.  
  286. void StartTopic(char *header, char *marker, char *desc)
  287. {
  288.   if ( sub )
  289.   {
  290.     testSubtopic(marker);
  291.     if ( fprintf(subtopics, "\004%u\005%s\005  %s",
  292.       ++currentID, marker, desc) == EOF )
  293.     diskFull(true);
  294.   }
  295.   else
  296.   {
  297.     sprintf(tempPtr, "\004%u\005%s\005  %s", ++currentID, marker, desc);
  298.     tempPtr += strlen(tempPtr);
  299.     buffered++;
  300.   }
  301.  
  302.   fprintf(output, "!TOPIC %u %s\n", currentID, header);
  303.   if ( indexed )
  304.     indexNo++;
  305.   fprintf(output, indexed ? "!INDEX %u\n" : "!NOINDEX\n", indexNo);
  306. }
  307.  
  308.  
  309. void StartList(void)
  310. {
  311.   sprintf(tempPtr, "\004%u\005INT %s\005  (list)\n",
  312.     ++currentID, category);
  313.   tempPtr += strlen(tempPtr);
  314.   buffered++;
  315.   fprintf(subtopics, "!TOPIC %u %s (list)\n!NOINDEX\n",
  316.     currentID, category);
  317.  
  318.   sub = 1;
  319.   subindeces = 0;
  320.   activeSub = currentID;
  321. }
  322.  
  323.  
  324. /* void EndList(void) - not used */
  325.  
  326.  
  327. /* char *NextID(void) - not used */
  328.  
  329.  
  330. int RecognizedTopic(void)
  331. {
  332.   char *ptr, *pdesc, topic[4], header[16], marker[20];
  333.   int i;
  334.  
  335.   if ( _fgets(line2, sizeof(line2), input) == NULL )
  336.     return 0;
  337.  
  338.   if ( (ptr = strchr(line1, '-')) == NULL )
  339.     return 0;
  340.  
  341.   pdesc = ptr;
  342.   while ( isspace(*--ptr) ) /* through spaces/tabs */
  343.     ;
  344.   while ( !isspace(*--ptr) ) /* through NNh */
  345.     ;
  346.   strncpy(topic, ++ptr, 2); /* interrupt number */
  347.   topic[2] = '\0';
  348.  
  349.   if ( strcmp(category, topic) )
  350.   {
  351.     sub = 0;
  352.     copyBuffer();
  353.     strcpy(category, topic);
  354.     fprintf(stderr, "%s\015", topic); /* show progress */
  355.   }
  356.   else
  357.     fprintf(output, "\004%u\005INT %s\005 (continued)\n",
  358.       currentID+1, topic);
  359.     /* insert a reference to this one in the former topic */
  360.  
  361.   strcpy(header, topic);
  362.  
  363.   for (ptr = line2 ; isspace(*ptr) ; ptr++)
  364.      ;
  365.  
  366.   if ( !strncmp(ptr, "AX =", 4) ||
  367.     !strncmp(ptr, "AH =", 4) ||
  368.     !strncmp(ptr, "AL =", 4)
  369.       )
  370.   {
  371.     for ( i = 5; (tolower(ptr[i]) != 'h') && !isspace(ptr[i]); i++ )
  372.       ;
  373.     if ( i < 11 )
  374.     {
  375.       if ( !sub )
  376.     StartList();
  377.       strcat(header, "  ");
  378.       strncat(header, ptr, i);
  379.     }
  380.   }
  381.  
  382.   strcpy(marker, "INT ");
  383.   strcat(marker, header);
  384.  
  385.   StartTopic(header, marker, pdesc);
  386.  
  387.   _fputs(line1, output);
  388.   if ( !divider_line(line2) )
  389.     _fputs(line2, output);
  390.  
  391.   return 1;
  392. }
  393.  
  394.  
  395. void CopyTopic(void)
  396. {
  397.   if ( divider_line(line2) )
  398.   { /* kludge for one-line interrupts */
  399.     _fgets(line1, sizeof(line2), input);
  400.     return;
  401.   }
  402.  
  403.   for (;;)
  404.   {
  405.     if ( _fgets(line1, sizeof(line1), input) == NULL )
  406.       break;
  407.  
  408.     if ( !divider_line(line1) )
  409.       _fputs(line1, output);
  410.     else
  411.     {
  412.       if ( _fgets(line2, sizeof(line2), input) == NULL )
  413.     break;
  414.  
  415.       if ( strncmp(line2, "INT ", 4) )
  416.       {
  417.     _fputs(line1, output);
  418.     _fputs(line2, output);
  419.       }
  420.       else
  421.       {
  422.     strcpy(line1, line2);
  423.     break;
  424.       }
  425.     }
  426.   }
  427. }
  428.  
  429. void configError(void)
  430. {
  431.   errorexit("\nFormat error in configuration file.\n");
  432. } /* configError */
  433.  
  434. void readconfig(void)
  435. /* reads one line from file config to line2 */
  436. {
  437.   if ( fgets(line2, sizeof(line2), config) == NULL )
  438.     configError();
  439. } /* readconfig */
  440.  
  441. void copyline(char *str, int len)
  442. /* copies line2 (after deleting the terminating '\n') to str
  443.     for max len characters. */
  444. {
  445.   line2[strlen(line2)-1] = 0; /* ignore '\n' */
  446.   strncpy(str, line2, len);
  447.   str[--len] = 0;
  448. } /* copyline */
  449.  
  450. void configurate(void)
  451. /* parses configuration file */
  452. {
  453. #define maxHeader 14
  454. #define markerLen 12
  455.   int confv, confsubv, command, extraTopics, i;
  456.   char header[(maxHeader+2) & 0xFE], marker[(markerLen+2) & 0xFE],
  457.     desc[(76-markerLen) & 0xFE], filename[80];
  458.   config = fopen(configfile, "r");
  459.   if ( config == NULL )
  460.   {
  461.     fputs("\nWarning: No configuration file.\n", stderr);
  462.     return;
  463.   }
  464.   readconfig();
  465.   if ( strncmp(line2, configmarker, strlen(configmarker)) )
  466.     configError();
  467.   readconfig();
  468.   if ( sscanf(line2, "%u%u", &confv, &confsubv) < 2 ) /* currently not used */
  469.     configError();
  470.   while ( !feof(config) )
  471.   {
  472.     while ( (fgets(line2, sizeof(line2), config) != NULL)
  473.       && (line2[0] == ';') ) ;
  474.     if feof(config) break;
  475.     copyline(filename, 79);
  476.     readconfig();
  477.     copyline(header, maxHeader);
  478.     readconfig();
  479.     copyline(marker, markerLen);
  480.     i = strlen(marker);
  481.     while ( i<markerLen-1 ) /* pad with spaces if short */
  482.       marker[i++] = ' '; /* is already 0-terminated at markerLen */
  483.     readconfig();
  484.     copyline(desc, 76-markerLen-2);
  485.     if ( desc[76-markerLen-2-1] )
  486.       desc[76-markerLen-2-1] = '\n'; /* truncate if necessary */
  487.     readconfig();
  488.     if ( sscanf(line2, "%u%u", &command, &extraTopics) < 2 )
  489.       configError();
  490.  
  491.     StartTopic(header, marker, desc);
  492.     CopyFile(filename, command);
  493.     currentID += extraTopics;
  494.   }
  495.   fclose(config);
  496. #undef maxHeader
  497. #undef markerLen
  498. } /* configurate */
  499.  
  500. void main(void)
  501. {
  502.   fprintf(stderr, "\nINT2GUID %s - (c) Kai Uwe Rommel/Bent Lynggaard - %s\n",
  503.     VERSION, __DATE__);
  504.   atexit(exitfunc);
  505.  
  506.   Initialize(); /* uses topic 1 */
  507.  
  508.   fputs("Including:\n",stderr);
  509.   StartTopic("Copyright etc.", "Copyright  ", "and references.\n");
  510.   if ( CopyFile("int2guid.ref", true) ) /* topic 2 */
  511.     errorexit(missingFile);
  512.  
  513.   StartTopic("INTERRUP.LST", "HEADER     ", "Overview of the Interrupt List\n");
  514.   fputs("(See also \4""4\5INTERRUP.1ST\5)\n", output); /* insert reference */
  515.   CopyTopic(); /* topic 3 */
  516.  
  517.   StartTopic("INTERRUP.1ST", "Mail etc.  ", "How to get/update INTERRUP.LST\n");
  518.   if ( CopyFile("interrup.1st", false) ) /* topic 4 */
  519.     errorexit(missingFile);
  520.  
  521.   StartTopic("GUIDE Program", "GUIDE      ", "Popup Reference Engine.\n");
  522.   if ( CopyFile("int2guid.gui", true) ) /* topic 5 */
  523.     errorexit(missingFile);
  524.  
  525.   configurate();
  526.  
  527.   indexed = 0;
  528.   indexNo = mainIndex;
  529.  
  530.   while ( RecognizedTopic() )
  531.     CopyTopic();
  532.  
  533.   Cleanup();
  534.  
  535.   exit(0);
  536. }
  537.  
  538. /* End of INT2GUID.C */
  539.